using AutoMapper;
using CoreManager.Core.Extensions;
using CoreManager.Models.DTOs;
using CoreManager.Models.Entities;
using CoreManager.Repository.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Linq.Expressions;
using System.Transactions;

namespace CoreManager.Services.Users
{
    /// <summary>
    /// 用户服务实现
    /// </summary>
    public class UserService : IUserService
    {
        private readonly IRepository<User> _userRepository;
        private readonly IRepository<Role> _roleRepository;
        private readonly IRepository<UserRole> _userRoleRepository;
        private readonly IMapper _mapper;
        private readonly ILogger<UserService> _logger;

        public UserService(
            IRepository<User> userRepository,
            IRepository<Role> roleRepository,
            IRepository<UserRole> userRoleRepository,
            IMapper mapper,
            ILogger<UserService> logger)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _userRoleRepository = userRoleRepository;
            _mapper = mapper;
            _logger = logger;
        }

        /// <summary>
        /// 获取用户列表（分页）
        /// </summary>
        public async Task<ApiResponse<PagedResponse<UserDto>>> GetUsersAsync(
            int pageIndex = 1, 
            int pageSize = 20,
            string? userName = null,
            string? realName = null,
            string? email = null,
            int? status = null)
        {
            try
            {
                // 构建基础查询表达式
                Expression<Func<User, bool>> queryExpression = u => true;

                // 用户名模糊查询
                if (!string.IsNullOrWhiteSpace(userName))
                {
                    queryExpression = queryExpression.And(u => u.UserName.Contains(userName));
                }

                // 真实姓名模糊查询
                if (!string.IsNullOrWhiteSpace(realName))
                {
                    queryExpression = queryExpression.And(u => u.RealName != null && u.RealName.Contains(realName));
                }

                // 邮箱模糊查询
                if (!string.IsNullOrWhiteSpace(email))
                {
                    queryExpression = queryExpression.And(u => u.Email != null && u.Email.Contains(email));
                }

                // 状态筛选
                if (status.HasValue)
                {
                    queryExpression = queryExpression.And(u => u.Status == status.Value);
                }

                var (users, total) = await _userRepository.GetPagedListAsync(
                    expression: queryExpression,
                    pageIndex: pageIndex,
                    pageSize: pageSize,
                    orderBy: u => u.CreateTime,
                    isAsc: false
                );

                var userDtos = new List<UserDto>();
                foreach (var user in users)
                {
                    var userDto = await ConvertToDtoAsync(user);
                    userDtos.Add(userDto);
                }

                var result = new PagedResponse<UserDto>
                {
                    Items = userDtos,
                    Total = total,
                    PageIndex = pageIndex,
                    PageSize = pageSize
                };

                return ApiResponse<PagedResponse<UserDto>>.Success(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取用户列表失败");
                return ApiResponse<PagedResponse<UserDto>>.Fail("获取用户列表失败");
            }
        }

        /// <summary>
        /// 根据ID获取用户
        /// </summary>
        public async Task<ApiResponse<UserDto>> GetUserByIdAsync(int id)
        {
            try
            {
                var user = await _userRepository.GetByIdAsync(id);
                if (user == null)
                {
                    return ApiResponse<UserDto>.Fail("用户不存在", 404);
                }

                var userDto = await ConvertToDtoAsync(user);
                return ApiResponse<UserDto>.Success(userDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取用户失败，ID: {Id}", id);
                return ApiResponse<UserDto>.Fail("获取用户失败");
            }
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        public async Task<ApiResponse<UserDto>> CreateUserAsync(CreateUserDto createDto, int currentUserId)
        {
            try
            {
                // 检查用户名是否已存在
                var existingUser = await _userRepository.GetAsync(u => u.UserName == createDto.UserName);
                if (existingUser != null)
                {
                    return ApiResponse<UserDto>.Fail("用户名已存在", 400);
                }

                // 检查邮箱是否已存在
                if (!string.IsNullOrEmpty(createDto.Email))
                {
                    var existingEmail = await _userRepository.GetAsync(u => u.Email == createDto.Email);
                    if (existingEmail != null)
                    {
                        return ApiResponse<UserDto>.Fail("邮箱已存在", 400);
                    }
                }

                var newUser = new User
                {
                    UserName = createDto.UserName,
                    Password = BCrypt.Net.BCrypt.HashPassword(createDto.Password),
                    RealName = createDto.RealName,
                    Email = createDto.Email,
                    Phone = createDto.Phone,
                    Status = createDto.Status,
                    Remark = createDto.Remark,
                    CreateUserId = currentUserId
                };

                var userId = await _userRepository.InsertAsync(newUser);
                newUser.Id = userId;

                _logger.LogInformation("用户创建成功，ID: {UserId}", userId);
                var userDto = await ConvertToDtoAsync(newUser);
                return ApiResponse<UserDto>.Success(userDto, "用户创建成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建用户失败");
                return ApiResponse<UserDto>.Fail("创建用户失败");
            }
        }

        /// <summary>
        /// 更新用户
        /// </summary>
        public async Task<ApiResponse<UserDto>> UpdateUserAsync(int id, UpdateUserDto updateDto, int currentUserId)
        {
            try
            {
                var existingUser = await _userRepository.GetByIdAsync(id);
                if (existingUser == null)
                {
                    return ApiResponse<UserDto>.Fail("用户不存在", 404);
                }

                // 检查邮箱是否被其他用户使用
                if (!string.IsNullOrEmpty(updateDto.Email) && updateDto.Email != existingUser.Email)
                {
                    var existingEmail = await _userRepository.GetAsync(u => u.Email == updateDto.Email && u.Id != id);
                    if (existingEmail != null)
                    {
                        return ApiResponse<UserDto>.Fail("邮箱已被其他用户使用", 400);
                    }
                }

                existingUser.RealName = updateDto.RealName;
                existingUser.Email = updateDto.Email;
                existingUser.Phone = updateDto.Phone;
                existingUser.Status = updateDto.Status;
                existingUser.Remark = updateDto.Remark;
                existingUser.UpdateUserId = currentUserId;

                await _userRepository.UpdateAsync(existingUser);

                _logger.LogInformation("用户更新成功，ID: {Id}", id);
                var userDto = await ConvertToDtoAsync(existingUser);
                return ApiResponse<UserDto>.Success(userDto, "用户更新成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新用户失败，ID: {Id}", id);
                return ApiResponse<UserDto>.Fail("更新用户失败");
            }
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        public async Task<ApiResponse<bool>> DeleteUserAsync(int id, int currentUserId)
        {
            try
            {
                var user = await _userRepository.GetByIdAsync(id);
                if (user == null)
                {
                    return ApiResponse<bool>.Fail("用户不存在", 404);
                }

                // 不能删除自己
                if (id == currentUserId)
                {
                    return ApiResponse<bool>.Fail("不能删除自己", 400);
                }

                await _userRepository.SoftDeleteAsync(id);

                _logger.LogInformation("用户删除成功，ID: {Id}", id);
                return ApiResponse<bool>.Success(true, "用户删除成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除用户失败，ID: {Id}", id);
                return ApiResponse<bool>.Fail("删除用户失败");
            }
        }

        /// <summary>
        /// 批量删除用户
        /// </summary>
        public async Task<ApiResponse<bool>> BatchDeleteUsersAsync(List<int> ids, int currentUserId)
        {
            try
            {
                if (ids == null || !ids.Any())
                {
                    return ApiResponse<bool>.Fail("请选择要删除的用户", 400);
                }

                if (ids.Contains(currentUserId))
                {
                    return ApiResponse<bool>.Fail("不能删除自己", 400);
                }

                foreach (var id in ids)
                {
                    await _userRepository.SoftDeleteAsync(id);
                }

                _logger.LogInformation("批量删除用户成功，删除数量: {Count}", ids.Count);
                return ApiResponse<bool>.Success(true, $"成功删除 {ids.Count} 个用户");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除用户失败");
                return ApiResponse<bool>.Fail("批量删除用户失败");
            }
        }

        /// <summary>
        /// 重置用户密码
        /// </summary>
        public async Task<ApiResponse<bool>> ResetPasswordAsync(int id, string newPassword, int currentUserId)
        {
            try
            {
                var user = await _userRepository.GetByIdAsync(id);
                if (user == null)
                {
                    return ApiResponse<bool>.Fail("用户不存在", 404);
                }

                // 使用BCrypt加密新密码
                user.Password = BCrypt.Net.BCrypt.HashPassword(newPassword);
                user.UpdateTime = DateTime.Now;
                user.UpdateUserId = currentUserId;

                await _userRepository.UpdateAsync(user);

                _logger.LogInformation("重置用户密码成功，用户ID: {Id}", id);
                return ApiResponse<bool>.Success(true, "密码重置成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "重置用户密码失败，用户ID: {Id}", id);
                return ApiResponse<bool>.Fail("重置用户密码失败");
            }
        }

        /// <summary>
        /// 切换用户状态
        /// </summary>
        public async Task<ApiResponse<bool>> ToggleUserStatusAsync(int id, int status, int currentUserId)
        {
            try
            {
                var user = await _userRepository.GetByIdAsync(id);
                if (user == null)
                {
                    return ApiResponse<bool>.Fail("用户不存在", 404);
                }

                // 不能禁用自己
                if (id == currentUserId && status == 0)
                {
                    return ApiResponse<bool>.Fail("不能禁用自己", 400);
                }

                user.Status = status;
                user.UpdateTime = DateTime.Now;
                user.UpdateUserId = currentUserId;

                await _userRepository.UpdateAsync(user);

                var statusText = status == 1 ? "启用" : "禁用";
                _logger.LogInformation("{StatusText}用户成功，用户ID: {Id}", statusText, id);
                return ApiResponse<bool>.Success(true, $"用户{statusText}成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "切换用户状态失败，用户ID: {Id}", id);
                return ApiResponse<bool>.Fail("切换用户状态失败");
            }
        }

        /// <summary>
        /// 分配用户角色
        /// </summary>
        public async Task<ApiResponse<bool>> AssignUserRolesAsync(AssignUserRolesDto assignDto, int currentUserId)
        {
            using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
            try
            {
                var user = await _userRepository.GetByIdAsync(assignDto.UserId);
                if (user == null)
                {
                    return ApiResponse<bool>.Fail("用户不存在", 404);
                }

                // 验证角色是否存在
                if (assignDto.RoleIds.Any())
                {
                    var existingRoles = await _roleRepository.GetQueryable()
                        .Where(r => assignDto.RoleIds.Contains(r.Id) && !r.IsDeleted)
                        .ToListAsync();

                    if (existingRoles.Count != assignDto.RoleIds.Count)
                    {
                        return ApiResponse<bool>.Fail("部分角色不存在", 400);
                    }
                }

                // 获取用户所有的角色关联（包括软删除的）
                var allUserRoles = await _userRoleRepository.GetQueryable()
                    .Where(ur => ur.UserId == assignDto.UserId)
                    .ToListAsync();

                // 处理每个角色关联
                foreach (var userRole in allUserRoles)
                {
                    if (assignDto.RoleIds.Contains(userRole.RoleId))
                    {
                        // 如果新角色列表中包含此角色，确保它是激活状态
                        if (userRole.IsDeleted)
                        {
                            userRole.IsDeleted = false;
                            userRole.UpdateTime = DateTime.Now;
                            userRole.UpdateUserId = currentUserId;
                            await _userRoleRepository.UpdateAsync(userRole);
                        }
                    }
                    else
                    {
                        // 如果新角色列表中不包含此角色，软删除它
                        if (!userRole.IsDeleted)
                        {
                            await _userRoleRepository.SoftDeleteAsync(userRole.Id);
                        }
                    }
                }

                // 添加新的角色关联（只添加数据库中不存在的）
                var existingRoleIds = allUserRoles.Select(ur => ur.RoleId).ToList();
                var newRoleIds = assignDto.RoleIds.Where(roleId => !existingRoleIds.Contains(roleId)).ToList();

                foreach (var roleId in newRoleIds)
                {
                    var userRole = new UserRole
                    {
                        UserId = assignDto.UserId,
                        RoleId = roleId,
                        CreateUserId = currentUserId
                    };

                    await _userRoleRepository.InsertAsync(userRole);
                }

                scope.Complete();
                _logger.LogInformation("用户角色分配成功，用户ID: {UserId}", assignDto.UserId);
                return ApiResponse<bool>.Success(true, "用户角色分配成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分配用户角色失败，用户ID: {UserId}", assignDto.UserId);
                return ApiResponse<bool>.Fail("分配用户角色失败");
            }
        }

        /// <summary>
        /// 获取用户的角色列表
        /// </summary>
        public async Task<ApiResponse<List<RoleDto>>> GetUserRolesAsync(int userId)
        {
            try
            {
                var user = await _userRepository.GetByIdAsync(userId);
                if (user == null)
                {
                    return ApiResponse<List<RoleDto>>.Fail("用户不存在", 404);
                }

                var userRoles = await _userRoleRepository.GetQueryable()
                    .Where(ur => ur.UserId == userId && !ur.IsDeleted)
                    .Join(_roleRepository.GetQueryable().Where(r => !r.IsDeleted),
                        ur => ur.RoleId,
                        r => r.Id,
                        (ur, r) => new RoleDto
                        {
                            Id = r.Id,
                            RoleName = r.RoleName,
                            RoleCode = r.RoleCode,
                            Sort = r.Sort,
                            Status = r.Status,
                            Remark = r.Remark,
                            CreateTime = r.CreateTime,
                            UpdateTime = r.UpdateTime
                        })
                    .ToListAsync();

                return ApiResponse<List<RoleDto>>.Success(userRoles);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取用户角色失败，用户ID: {UserId}", userId);
                return ApiResponse<List<RoleDto>>.Fail("获取用户角色失败");
            }
        }

        #region 私有方法

        /// <summary>
        /// 转换User实体为UserDto
        /// </summary>
        private async Task<UserDto> ConvertToDtoAsync(User user)
        {
            var userDto = new UserDto
            {
                Id = user.Id,
                UserName = user.UserName,
                RealName = user.RealName,
                Email = user.Email,
                Phone = user.Phone,
                Avatar = user.Avatar,
                Status = user.Status,
                LastLoginTime = user.LastLoginTime?.ToString("yyyy-MM-dd HH:mm:ss"),
                LastLoginIp = user.LastLoginIp,
                Remark = user.Remark,
                CreateTime = user.CreateTime.ToString("yyyy-MM-dd HH:mm:ss"),
                UpdateTime = user.UpdateTime?.ToString("yyyy-MM-dd HH:mm:ss"),
                RoleIds = new List<int>(),
                Roles = new List<RoleDto>()
            };

            // 获取用户角色信息
            var userRoles = await _userRoleRepository.GetQueryable()
                .Where(ur => ur.UserId == user.Id && !ur.IsDeleted)
                .Join(_roleRepository.GetQueryable().Where(r => !r.IsDeleted),
                    ur => ur.RoleId,
                    r => r.Id,
                    (ur, r) => new RoleDto
                    {
                        Id = r.Id,
                        RoleName = r.RoleName,
                        RoleCode = r.RoleCode,
                        Sort = r.Sort,
                        Status = r.Status,
                        Remark = r.Remark,
                        CreateTime = r.CreateTime,
                        UpdateTime = r.UpdateTime
                    })
                .ToListAsync();

            userDto.Roles = userRoles;
            userDto.RoleIds = userRoles.Select(r => r.Id).ToList();

            return userDto;
        }

        #endregion
    }
}

